import runningIcon from '@/assets/home/mapMarkers/running.png'
import warnningIcon from '@/assets/home/mapMarkers/warnning.png'
import rescuedIcon from '@/assets/home/mapMarkers/rescued.png'

import normalSpot from '@/assets/home/mapOverlay/normal_spot.png'
import runningInfo from '@/assets/home/mapOverlay/running_info.png'
import warningInfo from '@/assets/home/mapOverlay/warning_info.png'

import kunshanPoints from '@/data/kunshan-boundaries.json'

export const getSuitableZoomNumber = () => {
    // Simple considerations
    return window.innerWidth > 1440 ? (window.innerWidth > 1920 ? 13 : 12) : 11
}

export const getAreaBoundaries = (areaName: string) => {
    return new Promise<BMapGL.Point[]>((reslove) => {
        try {
            const bdary = new BMapGL.Boundary();

            bdary.get(areaName, ({ boundaries }) => {
                const reslut = boundaries.reduce((ev: BMapGL.Point[], boundary) => {
                    const ptArr = boundary.split(';').map(xy => {
                        const [x, y] = xy.split(',');

                        return new BMapGL.Point(x, y);
                    });

                    return [...ev, ...ptArr]
                }, [])

                reslove(reslut);
            })
        } catch (error) {
            console.error(error);
            console.info(`Get ${areaName} points unsuccessfly, will use static JSON data`);

            reslove(kunshanPoints);
        }
    })
}

export const generateMask = (coordinatePoints: BMapGL.Point[]) => {
    return new BMapGL.MapMask(coordinatePoints, {
        isBuildingMask: true,
        isPoiMask: true,
        isMapMask: true,
        showRegion: 'inside',
        topFillColor: '#5679ea',
        topFillOpacity: 0.5,
        sideFillColor: '#5679ea',
        sideFillOpacity: 0.9
    }) as BMapGL.Overlay;
}

export const generatePolyline = (coordinatePoints: BMapGL.Point[]) => {
    return new BMapGL.Polyline(coordinatePoints, {
        strokeColor: '#4ca7a2',
        strokeWeight: 3,
        strokeOpacity: 1
    });
}

const allMarkers:BMapGL.Marker[]  = [];

interface SetMarkerArgs<T>{
    map: BMapGL.Map,
    items: Array<T>,
    getMarkerPosition: (arg: T) => [number, number],
    getStatus: (arg: T) => keyof MarkerIconMap,
    showInfo: (arg: T | null, arg1: {
        REMOVE_ALERT_TIMEOUT_ID: NodeJS.Timeout | null
    }) => void,
    markerCategories: {
        running: boolean | undefined;
        warning: boolean | undefined;
        inMaintenance: boolean | undefined;
        rescueSite: boolean | undefined;
        rescuedToday: boolean | undefined;
    },
    isDetailPage?: boolean
}

export const setMarkers = <T>({
    map,
    items,
    getMarkerPosition,
    getStatus,
    showInfo,
    markerCategories,
    isDetailPage
}: SetMarkerArgs<T>) => {
    if (!isDetailPage) {
        allMarkers.forEach(m => map.removeOverlay(m));
    }

    const DATA: {
        REMOVE_ALERT_TIMEOUT_ID: NodeJS.Timeout | null
    } = {
        REMOVE_ALERT_TIMEOUT_ID : null
    }

    if (!items?.length) {
        return;
    }

    const markerIconMap: MarkerIconMap = {
        running: runningIcon,
        warning: warnningIcon,
        rescueSite: rescuedIcon,
        inMaintenance: rescuedIcon,
        rescuedToday: rescuedIcon,
    }

    const getMarker = (image: string, size: [number, number]) => {
        return new BMapGL.Icon(image, new BMapGL.Size(...size))
    }

    items.forEach(item => {
        const status = getStatus(item);
        
        if (!markerCategories[status]) {
            return;
        }
    
        let size: [number, number] = [20, 20];

        if (status === 'warning') {
            size = [20, 30];
        }
    
        const marker = new BMapGL.Marker(new BMapGL.Point(...getMarkerPosition(item)), {
            icon: getMarker(markerIconMap[status], size)
        });

        allMarkers.push(marker);
        map.addOverlay(marker);
        marker.addEventListener('onmouseover', () => {
            if (DATA.REMOVE_ALERT_TIMEOUT_ID) {
                clearTimeout(DATA.REMOVE_ALERT_TIMEOUT_ID);
                DATA.REMOVE_ALERT_TIMEOUT_ID = null;
            }
            showInfo(item, DATA);
        })
        marker.addEventListener('onmouseout', () => {
            DATA.REMOVE_ALERT_TIMEOUT_ID = setTimeout(() => {
                showInfo(null, DATA);
            }, 300);
        })
    })
}

export const showMarkerInfo = (map: BMapGL.Map) => {
    let customOverlay: BMapGL.CustomOverlay | null = null;

    return (info: Alert | null, data: {
        REMOVE_ALERT_TIMEOUT_ID: NodeJS.Timeout | null
    }) => {
        if (customOverlay) {
            map.removeOverlay(customOverlay as BMapGL.Overlay);
        }

        if (!info) return;

        const offsetX = -248 * window.innerWidth / 3840;

        customOverlay = new BMapGL.CustomOverlay(createMarkerInfoDom, {
            point: new BMapGL.Point(...info.point),
            opacity: 0.5,
            offsetY: -41,
            offsetX,
            properties: { ...info, data, removeOverlay: () => {
                map.removeOverlay(customOverlay as BMapGL.Overlay);
            } }
        });

        if (customOverlay) {
            map.addOverlay(customOverlay as BMapGL.Overlay);
        }
    }
}

function createMarkerInfoDom(this: BMapGL.CustomOverlayOther<{
    data: {
        REMOVE_ALERT_TIMEOUT_ID: NodeJS.Timeout
    },
    removeOverlay: () => void,
    status: 'warning' | 'running' | 'rescueSite',
    deviceSpec: string,
    info?: {
        number: string,
        address: string
    }
}>) {
    const wrapper = document.createElement('div');

    wrapper.addEventListener('mouseover', () => {
        clearTimeout(this.properties.data.REMOVE_ALERT_TIMEOUT_ID);
    })

    wrapper.addEventListener('mouseout', () => {
        this.properties.data.REMOVE_ALERT_TIMEOUT_ID = setTimeout(() => {
            this.properties.removeOverlay();
        }, 300)
    })

    let bgImage = normalSpot;

    if (this.properties.status === 'warning') {
        bgImage = warningInfo;
    }

    if (this.properties.status === 'running') {
        bgImage = runningInfo;
    }

    let content = `
        <div class="bmap_custom_window-running" data-running="${new Date().getSeconds()}">
            <div class="bmap_custom_window-running-title">电梯运行中</div>
            <div class="bmap_custom_window-running-site">
                <div><span>电梯编号</span><span>${this.properties?.info?.number || '--'}</span></div>
                <div><span>使用地址</span><span>${this.properties?.info?.address || '--'}</span></div>
            </div>
            <div class="bmap_custom_window-running-elevator">
                <img
                    src="https://iot.joylive.com/img/elevator_big_closing.5934565e.gif?t=${Math.floor(new Date().getSeconds() / 3)}"
                    alt="elevator"
                />
            </div>
            <div class="bmap_custom_window-running-elevator_triangle"></div>
            <div class="bmap_custom_window-running-elevator_floor-nun">2</div>
        <div>
    `

    if (this.properties.status === 'warning') {
        content = `
            <div class="bmap_custom_window-warning">
                <div><span>当前小区</span><span>东厂房西北侧</span></div>
                <div><span>电梯描述</span><span>${this.properties.deviceSpec || '--'}</span></div>
                <div><span>告警类型</span><span>困人</span></div>
                <div><span>报警编号</span><span>G14321</span></div>
                <div><span>场地地址</span><span>东厂房西北侧</span></div>
            </div>
            <div class="bmap_custom_window-warning-resue">
                <div><span>救援人员</span></div>
                <div><span>姓名</span><span class="bmap_custom_window-warning-resue-wait">待救援</span></div>
                <div><span>电话</span><span class="bmap_custom_window-warning-resue-wait">待救援</span></div>
            </div>
        `
    }

    if (this.properties.status === 'rescueSite') {
        content = `
            <div class="bmap_custom_window-spot">
                <div><span>站点名称</span><span>某某花园救援站</span></div>
                <div><span>服务人员总数</span><span>12人</span></div>
                <div><span>可服务人员</span><span>8人</span></div>
            </div>
        `
    }

    wrapper.innerHTML = `
        <div
            class="bmap_custom_window"
            style="background-image: url('${bgImage}'); background-repeat: no-repeat; background-size: contain"
        >
            ${content}
        </div>
    `

    return wrapper
}